import { describe, it, expect, beforeEach, vi } from 'vitest';
import { createPinia, setActivePinia } from 'pinia';
import { mount } from '@vue/test-utils';
import { useUploadStore } from '../../src/stores/uploadStore';
import { useStitchingStore } from '../../src/stores/stitchingStore';
import { useRestorationStore } from '../../src/stores/restorationStore';
import { generateTestImages } from './utils/imageGenerator';
import { measurePerformance, logPerformanceResult, runPerformanceTest } from './utils/performanceUtils';
import type { UploadedImage } from '../../src/types/models';
import '../integration/mocks/components';
import { 
  MockImageUploader, 
  MockImageGallery, 
  MockStitchingControls, 
  MockStitchedImageViewer,
  MockRestorationControls,
  MockRestoredImagesViewer,
  MockApp
} from '../integration/mocks/components';

// Helper function to convert File objects to UploadedImage objects
async function filesToUploadedImages(files: File[]): Promise<UploadedImage[]> {
  return files.map((file, index) => {
    // Extract dimensions from filename
    const match = file.name.match(/(\d+)x(\d+)/);
    const width = match ? parseInt(match[1]) : 800;
    const height = match ? parseInt(match[2]) : 600;
    
    return {
      id: `test-${index}`,
      file,
      url: URL.createObjectURL(file),
      name: file.name,
      width,
      height,
      fileSize: file.size,
      format: file.name.endsWith('.png') ? 'png' : 'jpg'
    };
  });
}

describe('UI Responsiveness Performance', () => {
  beforeEach(() => {
    // Create a fresh Pinia instance for each test
    setActivePinia(createPinia());
  });
  
  it('should measure ImageGallery rendering performance with different image counts', async () => {
    // Get upload store
    const uploadStore = useUploadStore();
    
    // Test with different numbers of images
    const imageCounts = [10, 50, 100];
    
    for (const count of imageCounts) {
      // Generate test images
      const files = await generateTestImages(count, 800, 800, 600, 600);
      const images = await filesToUploadedImages(files);
      
      // Set images in store
      uploadStore.images = images;
      
      // Measure performance
      const { performance } = await measurePerformance(
        `Render ImageGallery with ${count} images`,
        async () => {
          const gallery = mount(MockImageGallery);
          return gallery;
        },
        {
          imageCount: count
        }
      );
      
      // Log performance result
      logPerformanceResult(performance);
      
      // Verify that the rendering was successful
      expect(performance.duration).toBeGreaterThan(0);
    }
  });
  
  it('should measure StitchedImageViewer rendering performance with different image sizes', async () => {
    // Get stitching store
    const stitchingStore = useStitchingStore();
    
    // Test with different image sizes
    const imageSizes: Array<[number, number]> = [
      [1000, 800],     // Small: 0.8 MP
      [2000, 1600],    // Medium: 3.2 MP
      [4000, 3200]     // Large: 12.8 MP
    ];
    
    for (const [width, height] of imageSizes) {
      // Create a mock stitched image
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      
      // Set stitched image in store
      stitchingStore.stitchedImage = {
        id: 'test-stitched',
        canvas,
        width,
        height,
        url: 'blob:test'
      };
      
      // Measure performance
      const { performance } = await measurePerformance(
        `Render StitchedImageViewer with ${width}x${height} image (${(width * height / 1000000).toFixed(2)} MP)`,
        async () => {
          const viewer = mount(MockStitchedImageViewer);
          return viewer;
        },
        {
          imageSize: `${width}x${height}`,
          megapixels: (width * height / 1000000).toFixed(2)
        }
      );
      
      // Log performance result
      logPerformanceResult(performance);
      
      // Verify that the rendering was successful
      expect(performance.duration).toBeGreaterThan(0);
    }
  });
  
  it('should measure RestoredImagesViewer rendering performance with different image counts', async () => {
    // Get restoration store
    const restorationStore = useRestorationStore();
    
    // Test with different numbers of images
    const imageCounts = [10, 50, 100];
    
    for (const count of imageCounts) {
      // Create mock restored images
      const restoredImages = Array.from({ length: count }, (_, i) => {
        const canvas = document.createElement('canvas');
        canvas.width = 800;
        canvas.height = 600;
        
        return {
          id: `test-${i}`,
          name: `test-${i}.jpg`,
          canvas,
          width: 800,
          height: 600,
          url: `blob:test-${i}`,
          format: 'jpg'
        };
      });
      
      // Set restored images in store
      restorationStore.restoredImages = restoredImages;
      
      // Measure performance
      const { performance } = await measurePerformance(
        `Render RestoredImagesViewer with ${count} images`,
        async () => {
          const viewer = mount(MockRestoredImagesViewer);
          return viewer;
        },
        {
          imageCount: count
        }
      );
      
      // Log performance result
      logPerformanceResult(performance);
      
      // Verify that the rendering was successful
      expect(performance.duration).toBeGreaterThan(0);
    }
  });
  
  it('should measure component interaction performance', async () => {
    // Get stores
    const uploadStore = useUploadStore();
    const stitchingStore = useStitchingStore();
    
    // Generate test images
    const files = await generateTestImages(10, 800, 800, 600, 600);
    const images = await filesToUploadedImages(files);
    
    // Set images in store
    uploadStore.images = images;
    
    // Measure performance of clicking the stitch button
    const { performance: stitchButtonPerformance } = await measurePerformance(
      'Click stitch button',
      async () => {
        // Mock the stitchImages method
        stitchingStore.stitchImages = vi.fn().mockResolvedValue({
          id: 'test-stitched',
          canvas: document.createElement('canvas'),
          width: 2400,
          height: 1800,
          url: 'blob:test'
        });
        
        // Mount the component
        const controls = mount(MockStitchingControls);
        
        // Click the stitch button
        await controls.find('.stitch-button').trigger('click');
        
        return controls;
      }
    );
    
    // Log performance result
    logPerformanceResult(stitchButtonPerformance);
    
    // Verify that the interaction was successful
    expect(stitchButtonPerformance.duration).toBeGreaterThan(0);
    expect(stitchingStore.stitchImages).toHaveBeenCalled();
    
    // Measure performance of clicking the download button
    stitchingStore.stitchedImage = {
      id: 'test-stitched',
      canvas: document.createElement('canvas'),
      width: 2400,
      height: 1800,
      url: 'blob:test'
    };
    
    const { performance: downloadButtonPerformance } = await measurePerformance(
      'Click download button',
      async () => {
        // Mock the downloadStitchedImage method
        stitchingStore.downloadStitchedImage = vi.fn();
        
        // Mount the component
        const viewer = mount(MockStitchedImageViewer);
        
        // Click the download button
        await viewer.find('.download-button').trigger('click');
        
        return viewer;
      }
    );
    
    // Log performance result
    logPerformanceResult(downloadButtonPerformance);
    
    // Verify that the interaction was successful
    expect(downloadButtonPerformance.duration).toBeGreaterThan(0);
    expect(stitchingStore.downloadStitchedImage).toHaveBeenCalled();
  });
  
  it('should measure full app rendering performance', async () => {
    // Get stores
    const uploadStore = useUploadStore();
    const stitchingStore = useStitchingStore();
    const restorationStore = useRestorationStore();
    
    // Generate test images for upload store
    const files = await generateTestImages(5, 800, 800, 600, 600);
    const images = await filesToUploadedImages(files);
    uploadStore.images = images;
    
    // Create stitched image for stitching store
    const canvas = document.createElement('canvas');
    canvas.width = 2400;
    canvas.height = 1800;
    stitchingStore.stitchedImage = {
      id: 'test-stitched',
      canvas,
      width: 2400,
      height: 1800,
      url: 'blob:test'
    };
    
    // Create restored images for restoration store
    const restoredImages = Array.from({ length: 5 }, (_, i) => {
      const canvas = document.createElement('canvas');
      canvas.width = 800;
      canvas.height = 600;
      
      return {
        id: `test-${i}`,
        name: `test-${i}.jpg`,
        canvas,
        width: 800,
        height: 600,
        url: `blob:test-${i}`,
        format: 'jpg'
      };
    });
    restorationStore.restoredImages = restoredImages;
    
    // Measure performance of rendering the full app
    const { performance } = await measurePerformance(
      'Render full app with all components',
      async () => {
        const app = mount(MockApp);
        return app;
      },
      {
        uploadImageCount: images.length,
        stitchedImageSize: `${stitchingStore.stitchedImage.width}x${stitchingStore.stitchedImage.height}`,
        restoredImageCount: restoredImages.length
      }
    );
    
    // Log performance result
    logPerformanceResult(performance);
    
    // Verify that the rendering was successful
    expect(performance.duration).toBeGreaterThan(0);
  });
  
  it('should measure UI responsiveness under memory pressure', async () => {
    // Get upload store
    const uploadStore = useUploadStore();
    
    // Create a large number of images to simulate memory pressure
    const largeImageCount = 50;
    const files = await generateTestImages(largeImageCount, 1600, 1600, 1200, 1200);
    const images = await filesToUploadedImages(files);
    uploadStore.images = images;
    
    // Measure performance of rendering and interacting with the gallery under memory pressure
    const { performance } = await measurePerformance(
      'Render and interact with gallery under memory pressure',
      async () => {
        // Mount the gallery
        const gallery = mount(MockImageGallery);
        
        // Simulate some interactions
        if (gallery.findAll('.remove-button').length > 0) {
          await gallery.findAll('.remove-button')[0].trigger('click');
        }
        
        return gallery;
      },
      {
        imageCount: largeImageCount,
        totalMemoryUsage: images.reduce((sum, img) => sum + (img.fileSize || 0), 0)
      }
    );
    
    // Log performance result
    logPerformanceResult(performance);
    
    // Verify that the interaction was successful
    expect(performance.duration).toBeGreaterThan(0);
    expect(uploadStore.images.length).toBe(largeImageCount - 1); // One image was removed
  });
});